﻿namespace FiftyOne.Foundation.Mobile.Detection.Wurfl.Handlers
{
    using FiftyOne;
    using FiftyOne.Foundation.Mobile.Detection.Wurfl;
    using FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers;
    using System;
    using System.Collections.Generic;
    using System.Web;

    internal abstract class Handler
    {
        private List<string> _uaProfDomains = new List<string>();
        private SortedDictionary<int, DeviceInfo[]> _uaprofs = new SortedDictionary<int, DeviceInfo[]>();
        private SortedDictionary<int, DeviceInfo[]> _useragents = new SortedDictionary<int, DeviceInfo[]>();
        private const byte DEFAULT_CONFIDENCE = 5;
        private static readonly string[] UAPROF_CAPABILITIES = new string[] { "uaprof", "uaprof2", "uaprof3" };
        private static readonly string[] UAPROF_HEADERS = new string[] { "profile", "x-wap-profile", "X-Wap-Profile" };

        protected Handler()
        {
        }

        protected internal virtual bool CanHandle(DeviceInfo device)
        {
            if (this.SupportedRootDeviceIds == null)
            {
                return this.CanHandle(device.UserAgent);
            }
            return (this.CanHandleDevice(device) && this.CanHandle(device.UserAgent));
        }

        protected internal abstract bool CanHandle(string userAgent);
        internal virtual bool CanHandle(HttpRequest request)
        {
            bool flag = this.CanHandle(Provider.GetUserAgent(request));
            if (!flag && (this._uaProfDomains.Count > 0))
            {
                Uri result = null;
                foreach (string str in UAPROF_HEADERS)
                {
                    string uriString = request.Headers[str];
                    if (((uriString != null) && Uri.TryCreate(uriString, UriKind.Absolute, out result)) && this._uaProfDomains.Contains(result.Host))
                    {
                        return true;
                    }
                }
            }
            return flag;
        }

        private bool CanHandleDevice(DeviceInfo device)
        {
            if (device != null)
            {
                foreach (string str in this.SupportedRootDeviceIds)
                {
                    if (str == device.DeviceId)
                    {
                        return true;
                    }
                }
                return this.CanHandleDevice(device.FallbackDevice);
            }
            return false;
        }

        private static string CleanUaProf(string value)
        {
            return value.Replace("\"", "");
        }

        internal DeviceInfo GetDeviceInfo(string userAgent)
        {
            DeviceInfo[] deviceInfo = GetDeviceInfo(this._useragents, userAgent);
            if ((deviceInfo != null) && (deviceInfo.Length > 0))
            {
                if (deviceInfo.Length == 1)
                {
                    return deviceInfo[0];
                }
                foreach (DeviceInfo info in deviceInfo)
                {
                    if (info.UserAgent == userAgent)
                    {
                        return info;
                    }
                }
            }
            return null;
        }

        private static DeviceInfo[] GetDeviceInfo(SortedDictionary<int, DeviceInfo[]> _dictionary, string value)
        {
            int hashCode = value.GetHashCode();
            if (_dictionary.ContainsKey(hashCode))
            {
                return _dictionary[hashCode];
            }
            return null;
        }

        internal Results GetResultsFromUAProf(string uaprof)
        {
            DeviceInfo[] deviceInfo = GetDeviceInfo(this._uaprofs, uaprof);
            if ((deviceInfo != null) && (deviceInfo.Length > 0))
            {
                Results results = new Results();
                results.AddRange(deviceInfo);
                return results;
            }
            return null;
        }

        protected internal abstract Results Match(string userAgent);
        internal virtual Results Match(HttpRequest request)
        {
            string userAgent = Provider.GetUserAgent(request);
            DeviceInfo deviceInfo = this.GetDeviceInfo(userAgent);
            if (deviceInfo != null)
            {
                return new Results(deviceInfo);
            }
            if ((request.Headers != null) && (request.Headers.Count > 0))
            {
                foreach (string str2 in UAPROF_HEADERS)
                {
                    string str3 = request.Headers[str2];
                    if (!string.IsNullOrEmpty(str3))
                    {
                        str3 = CleanUaProf(str3);
                        Results resultsFromUAProf = this.GetResultsFromUAProf(str3);
                        if ((resultsFromUAProf != null) && (resultsFromUAProf.Count > 0))
                        {
                            if (EventLog.IsDebug)
                            {
                                EventLog.Debug(string.Format("UAProf matched '{0}' devices to header '{1}'.", resultsFromUAProf.Count, str3));
                            }
                            return resultsFromUAProf;
                        }
                    }
                }
            }
            return this.Match(userAgent);
        }

        internal virtual void Set(DeviceInfo device)
        {
            this.SetUserAgent(device);
            this.SetUAProf(device);
        }

        private void SetUAProf(DeviceInfo device)
        {
            foreach (string str in UAPROF_CAPABILITIES)
            {
                string capability = device.GetCapability(str);
                if (!string.IsNullOrEmpty(capability))
                {
                    capability = CleanUaProf(capability);
                    Uri result = null;
                    if (Uri.TryCreate(capability, UriKind.Absolute, out result))
                    {
                        int hashCode = capability.GetHashCode();
                        lock (this._uaprofs)
                        {
                            if (this._uaprofs.ContainsKey(hashCode))
                            {
                                int index = 0;
                                while (index < this._uaprofs[hashCode].Length)
                                {
                                    if (this._uaprofs[hashCode][index].DeviceId == device.DeviceId)
                                    {
                                        this._uaprofs[hashCode][index] = (DeviceInfo) device;
                                        break;
                                    }
                                    index++;
                                }
                                if (index == this._uaprofs[hashCode].Length)
                                {
                                    List<DeviceInfo> list = new List<DeviceInfo>(this._uaprofs[hashCode]);
                                    list.Add(device);
                                    this._uaprofs[hashCode] = list.ToArray();
                                }
                            }
                            else
                            {
                                this._uaprofs.Add(hashCode, new DeviceInfo[] { device });
                            }
                        }
                        lock (this._uaProfDomains)
                        {
                            if (!this._uaProfDomains.Contains(result.Host))
                            {
                                this._uaProfDomains.Add(result.Host);
                            }
                        }
                    }
                }
            }
        }

        private void SetUserAgent(DeviceInfo device)
        {
            int hashCode = device.UserAgent.GetHashCode();
            lock (this._useragents)
            {
                if (this._useragents.ContainsKey(hashCode))
                {
                    for (int i = 0; i < this._useragents[hashCode].Length; i++)
                    {
                        if (this._useragents[hashCode][i].UserAgent == device.UserAgent)
                        {
                            this._useragents[hashCode][i] = (DeviceInfo) device;
                            goto Label_00E9;
                        }
                    }
                    List<DeviceInfo> list = new List<DeviceInfo>(this._useragents[hashCode]);
                    list.Add(device);
                    this._useragents[hashCode] = list.ToArray();
                Label_00E9:;
                }
                else
                {
                    this._useragents.Add(hashCode, new DeviceInfo[] { device });
                }
            }
        }

        internal virtual byte Confidence
        {
            get
            {
                return 5;
            }
        }

        internal virtual DeviceInfo DefaultDevice
        {
            get
            {
                return Provider.DefaultDevice;
            }
        }

        protected virtual string[] SupportedRootDeviceIds
        {
            get
            {
                return null;
            }
        }

        internal SortedDictionary<int, DeviceInfo[]>.ValueCollection UserAgents
        {
            get
            {
                return this._useragents.Values;
            }
        }
    }
}

